package com.losalpes.buy;

import com.losalpes.catalog.ICatalogService;
import com.losalpes.client.IClientService;
import com.losalpes.persistence.IPersistenceServices;
import com.losalpes.persistence.entity.Ciudad;
import com.losalpes.persistence.entity.Cliente;
import com.losalpes.persistence.entity.Compra;
import com.losalpes.persistence.entity.CompraMuebles;
import com.losalpes.persistence.entity.ItemCompra;
import com.losalpes.persistence.entity.ItemMasVendido;
import com.losalpes.persistence.entity.Mueble;
import com.losalpes.persistence.entity.TipoMueble;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.faces.model.SelectItem;

/**
 * Clase que administra la logica de negocio de las compras
 * @author CSI
 */
@Stateless
@DeclareRoles({"Gerente"})
public class BuyService implements IBuyService {

    @EJB
    IPersistenceServices persistenceServices;

    /**
     * Constructor de la clase
     */
    public BuyService() {
    }

    /**
     * Permite añadir una compra
     * @param compra
     */
    public void add(Compra compra) {
        persistenceServices.create(compra);
    }

    /**
     * permite eliminar na compra
     * @param compra
     */
    public void delete(Compra compra) {
        persistenceServices.delete(compra);
    }

    /**
     * realiza una busqueda de todas las compras
     * @return Lista
     */
    public List<Compra> findAllCompras() {
        return (List<Compra>) persistenceServices.findAll(Compra.class);
    }

    /**
     * Permite verificar si un cliente tiene compras
     * @param idCliente id del cliente
     * @return booleano
     */
    public boolean hayComprasCliente(Cliente cliente) {
        String sql = "Select c from Compra c where c.cliente = :pCliente ";
        List lista = persistenceServices.findQuery(sql, "pCliente", cliente);

        return lista.size() > 0;
    }

    /**
     * Permite verificar si un mueble esta incluido en una compra
     * @param referencia
     * @return booleano
     */
    public boolean hayComprasMueble(Mueble mueble) {
        String sql = "Select c from ItemCompra i where i.mueble = :pMueble ";
        List lista = persistenceServices.findQuery(sql, "pMueble", mueble);

        return lista.size() > 0;
    }

    /**
     * Obtiene una lista de las comra del cliente
     * @param idCliente id del cliente
     * @return lista de compras asociadas
     */
    @RolesAllowed({"Gerente"})
    public List comprasCliente(Cliente cliente) {
        String sql = "Select c from Compra c where c.cliente = :pCliente ";
        return persistenceServices.findQuery(sql, "pCliente", cliente);
    }

    /**
     * Busca el producto mas vendido en un periodo de tiempo dado
     * @param fechaIni fecha inicial del periodo
     * @param fechaFin fecha final del periodo
     * @return La lista con elementos para saber ciudad y cantidades
     */
    @RolesAllowed({"Gerente"})
    public List productoMasVendido(Date fechaIni, Date fechaFin) {
        List<Compra> lcCompras = findAllCompras();

        ArrayList<ItemMasVendido> tmpMasVendido = new ArrayList<ItemMasVendido>();

        //1. Hacer una lista con la cuenta de los muebles
        for (Compra cCompra : lcCompras) {
            if (fechaIni.before(cCompra.getFecha()) && fechaFin.after(cCompra.getFecha())) {
                for (ItemCompra icItem : cCompra.getItems()) {
                    Boolean encontrado = false;
                    for (ItemMasVendido itemMasVendido : tmpMasVendido) {
                        if (icItem.getMueble().equals(itemMasVendido.getMueble())) {
                            itemMasVendido.setCantidad(itemMasVendido.getCantidad() + icItem.getCantidad());
                            encontrado = true;
                        }
                    }

                    if (!encontrado) {
                        tmpMasVendido.add(new ItemMasVendido(icItem.getCantidad(), null, icItem.getMueble()));
                    }
                }
            }
        }

        //2. Buscamos el mueble con mas ocurrencias
        ItemMasVendido item = null;
        Integer cantidad = 0;
        for (ItemMasVendido itemMasVendido : tmpMasVendido) {
            if (cantidad < itemMasVendido.getCantidad()) {
                item = itemMasVendido;
                cantidad = itemMasVendido.getCantidad();
            }
        }

        ArrayList<ItemMasVendido> productoMasVendidoList = new ArrayList<ItemMasVendido>();
        //3. Creamos la lista real
        for (Compra cCompra : lcCompras) {
            if (fechaIni.before(cCompra.getFecha()) && fechaFin.after(cCompra.getFecha())) {
                for (ItemCompra icItem : cCompra.getItems()) {
                    Boolean encontrado = false;

                    if (item.getMueble().equals(icItem.getMueble())) {
                        for (ItemMasVendido itemMasVendido : productoMasVendidoList) {
                            if (icItem.getMueble().equals(itemMasVendido.getMueble()) && cCompra.getCliente().getCiudadResidencia().equals(itemMasVendido.getCiudad())) {
                                itemMasVendido.setCantidad(itemMasVendido.getCantidad() + icItem.getCantidad());
                                encontrado = true;
                            }
                        }

                        if (!encontrado) {
                            productoMasVendidoList.add(new ItemMasVendido(icItem.getCantidad(), cCompra.getCliente().getCiudadResidencia(), icItem.getMueble()));
                        }
                    }
                }
            }
        }
        return productoMasVendidoList;
    }

    /**
     * Obtiene el nombre de una ciudad basado en el Id
     * @param ciudad
     * @return
     */
    public String nombreCiudad(int id) {
        Ciudad ciudad = (Ciudad)persistenceServices.findById(Ciudad.class, id);
        return ciudad.getNombre() + " - " + ciudad.getDepartamento().getNombre() + " - " + ciudad.getDepartamento().getPais().getNombre();
    }

    /**
     * Permite obtener una lista de las venas diarias por tipo de mubel
     * @param ciudad
     * @param fechaIni
     * @param fechaFin
     * @param tipo
     * @return
     */
    @RolesAllowed({"Gerente"})
    public List ventasDiariasTipo(Ciudad ciudad, Date fechaIni, Date fechaFin, TipoMueble tipo) {
        /*ArrayList<String> parametrosNombre = new ArrayList<String>();
        ArrayList<Object> parametrosValor = new ArrayList<Object>();

        parametrosNombre.add("pFechaInicio");
        parametrosValor.add(fechaIni);

        parametrosNombre.add("pFechaFin");
        parametrosValor.add(fechaFin);

        //parametrosNombre.add("pTipo");
        //parametrosValor.add(tipo);

        parametrosNombre.add("pCiudad");
        parametrosValor.add(ciudad);
*/
        //String sql = "Select c.items from Compra c where c.fecha>= :pFechaInicio and c.fecha<= :pFechaFin and c.cliente.ciudadResidencia = :pCiudad  ";
        String sql = "Select c.items from Compra c ";

        return persistenceServices.findQuery(sql);

        //return persistenceServices.findQuery(sql, parametrosNombre, parametrosValor);
    }

    /**
     * Obtiene una lista de documentos
     * @return
     */
    public SelectItem[] getDocumentos() {
        String sql = "Select c.cliente from Compra c  ";
        List<Cliente> lista = persistenceServices.findQuery(sql);

        ArrayList<SelectItem> items = new ArrayList<SelectItem>();
        for (Cliente cliente : lista) {
            items.add(new SelectItem(cliente.getDocumento(), cliente.getDocumento()));
        }

        SelectItem[] c = new SelectItem[items.size()];
        return items.toArray(c);
    }
}